package com.example.mediamoudle.scaletime.view

import android.content.Context
import android.util.AttributeSet
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import android.view.View
import android.widget.FrameLayout
import androidx.dynamicanimation.animation.DynamicAnimation
import androidx.dynamicanimation.animation.FlingAnimation
import androidx.dynamicanimation.animation.FloatValueHolder
import com.example.mediamoudle.scaletime.value.TimeLineBaseValue

class ZoomFrameLayout @JvmOverloads constructor(
    context: Context,
    attributeSet: AttributeSet? = null,
    defaultStyleAttr: Int = 0
) : FrameLayout(context, attributeSet, defaultStyleAttr),
    DynamicAnimation.OnAnimationUpdateListener {
    private var scaleEnable = true
    var timeLineValue = TimeLineBaseValue()

    /**
     * 是否支持缩放
     */
    fun setScaled(scale: Boolean) {
        this.scaleEnable = scale
    }
    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        return ev.pointerCount > 1 || super.onInterceptTouchEvent(ev)
    }
    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (!scaleEnable) return super.onTouchEvent(event)
        scaleGestureDetector.onTouchEvent(event)
        if (!scaleGestureDetector.isInProgress) {
            gestureDetector.onTouchEvent(event)
        }
        return true

    }

    private val scaleGestureDetector: ScaleGestureDetector by lazy(LazyThreadSafetyMode.NONE) {
        ScaleGestureDetector(context, scaleGestureListener)
    }
    var lastScaleEventTime = 0L
    val scaleGestureListener = object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
        override fun onScaleBegin(detector: ScaleGestureDetector): Boolean {
            return super.onScaleBegin(detector)
        }

        override fun onScale(detector: ScaleGestureDetector): Boolean {
            scaleEvent(timeLineValue.scale * detector.scaleFactor * detector.scaleFactor)
            return super.onScale(detector)
        }

        override fun onScaleEnd(detector: ScaleGestureDetector) {
            super.onScaleEnd(detector)
            lastScaleEventTime = detector.eventTime
        }
    }

    private fun scaleEvent(scaleFactor: Float) {
        flingAnimation.cancel()
        timeLineValue.scale = scaleFactor
        disPatchScaleChange()
    }


    private val gestureDetector: GestureDetector by lazy(LazyThreadSafetyMode.NONE) {
        GestureDetector(context, gestureListener)
    }

    val gestureListener = object : GestureDetector.SimpleOnGestureListener() {
        override fun onSingleTapUp(e: MotionEvent): Boolean {
            performClick()
            return super.onSingleTapUp(e)
        }

        override fun onScroll(
            e1: MotionEvent?,
            e2: MotionEvent,
            distanceX: Float,
            distanceY: Float
        ): Boolean {
            if (hasEventWithScale(e1, e2)) {
                return true
            }
            scrollEvent(distanceX, distanceY)
            return true
        }

        override fun onFling(
            e1: MotionEvent?,
            e2: MotionEvent,
            velocityX: Float,
            velocityY: Float
        ): Boolean {
            if (hasEventWithScale(e1, e2)) {
                return true
            }
            flingAnimation.apply {
                cancel()
                val max = timeLineValue.pxInSecond * timeLineValue.duration / 1000
                if (max > 0f && timeValueHolder.value in 0f..max) {
                    setStartVelocity(-velocityX)
                    setMinValue(0f)
                    setMaxValue(max)
                    start()
                }
            }

            return super.onFling(e1, e2, velocityX, velocityY)
        }
    }


    //按下后有过缩放事件就不处理滑动
    private fun hasEventWithScale(
        e1: MotionEvent?,
        e2: MotionEvent?
    ): Boolean {
        if (scaleGestureDetector.isInProgress) {
            return true
        }
        if (e1 != null && (lastScaleEventTime > e1.downTime || e1.pointerCount > 1)) {
            return true
        }

        return e2 != null && (lastScaleEventTime > e2.downTime || e2.pointerCount > 1)
    }

    private fun scrollEvent(distanceX: Float, distanceY: Float) {
        val offsetTime = (distanceX * 1000 / timeLineValue.pxInSecond).toLong()
        if (offsetTime != 0L) {
            flingAnimation.cancel()
            timeLineValue.time += offsetTime
            timeValueHolder.value = timeLineValue.time.toFloat() * timeLineValue.pxInSecond / 1000
            updateTimeByScroll(timeLineValue.time)

        }
    }


    /** 保存滑动事件*/
    private var timeValueHolder = FloatValueHolder()
    val flingAnimation = FlingAnimation(timeValueHolder).apply {
        addUpdateListener(this@ZoomFrameLayout)
    }

    /**
     * FlingAnimation
     */
    override fun onAnimationUpdate(animation: DynamicAnimation<*>?, value: Float, velocity: Float) {
        timeLineValue.time = timeLineValue.px2time(value)
        dispatchUpdateTime()
    }


    fun updateTime(time: Long) {
        timeLineValue.time = time
        dispatchUpdateTime()
    }

    fun isScrollIng(): Boolean {
        return flingAnimation.isRunning
    }
    private fun updateTimeByScroll(time: Long) {
        updateTime(time)
    }
    /**
     * 分发时间线数据
     */
    fun dispatchTimeLineValue() = dispatchTimeLineEvent(false) {
        it.timeLineValue = timeLineValue
    }
    /**
     * 分发缩放数据
     */
    private fun disPatchScaleChange() = dispatchTimeLineEvent{
          it.scaleChange()
    }
    /**
     * 分发时间更新
     */
    fun dispatchUpdateTime() = dispatchTimeLineEvent {
        it.updateTime()
    }

    /** 传递时间轴事件 */
    private fun dispatchTimeLineEvent(
        filterHidden: Boolean = true, //隐藏view不用分发事件
        event: (TimeLineBaseValue.TimeLineBaseView) -> Unit
    ) {
        for (i in 0..childCount) {
            val childAt = getChildAt(i)
            if (childAt is TimeLineBaseValue.TimeLineBaseView && (!filterHidden || childAt.visibility == View.VISIBLE)) {
                event(childAt)
            }
        }

    }
}